﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace PickGold.Util.OCR
{
	/// <summary>
	/// 
	/// </summary>
	public static class BarCode
	{
		private const string Code93Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%";
		private const string Code39Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";

		#region private static readonly string[] Code93Codes
		private static readonly string[] Code93Codes =
		{
			"100010100",//0
			"101001000",//1
			"101000100",//2
			"101000010",//3
			"100101000",//4
			"100100100",//5
			"100100010",//6
			"101010000",//7
			"100010010",//8
			"100001010",//9
			"110101000",//A
			"110100100",//B
			"110100010",//C
			"110010100",//D
			"110010010",//E
			"110001010",//F
			"101101000",//G
			"101100100",//H
			"101100010",//I
			"100110100",//J
			"100011010",//K
			"101011000",//L
			"101001100",//M
			"101000110",//N
			"100101100",//O
			"100010110",//P
			"110110100",//Q
			"110110010",//R
			"110101100",//S
			"110100110",//T
			"110010110",//U
			"110011010",//V
			"101101100",//W
			"101100110",//X
			"100110110",//Y
			"100111010",//Z
			"100101110",//-
			"111010100",//.
			"111010010",// 
			"111001010",//$
			"101101110",///
			"101101110",//+
			"110101110",//%
			"100100110",
			"111011010",
			"111010110",
			"100110010",
			"101011110",
			"1010111101",
		};
		#endregion

		#region private static readonly string[] Code39Codes
		private static readonly string[,] Code39Codes = 
		{
			{ "000110100", "1010011011010", },//0
			{ "100100001", "1101001010110", },//1
			{ "001100001", "1011001010110", },//2
			{ "101100000", "1101100101010", },//3
			{ "000110001", "1010011010110", },//4
			{ "100110000", "1101001101010", },//5
			{ "001110000", "1011001101010", },//6
			{ "000100101", "1010010110110", },//7
			{ "100100100", "1101001011010", },//8
			{ "001100100", "1011001011010", },//9
			{ "100001001", "1101010010110", },//A
			{ "001001001", "1011010010110", },//B
			{ "101001000", "1101101001010", },//C
			{ "000011001", "1010110010110", },//D
			{ "100011000", "1101011001010", },//E
			{ "001011000", "1011011001010", },//F
			{ "000001101", "1010100110110", },//G
			{ "100001100", "1101010011010", },//H
			{ "001001100", "1011010011010", },//I
			{ "000011100", "1010110011010", },//J
			{ "100000011", "1101010100110", },//K
			{ "001000011", "1011010100110", },//L
			{ "101000010", "1101101010010", },//M
			{ "000010011", "1010110100110", },//N
			{ "100010010", "1101011010010", },//O
			{ "001010010", "1011011010010", },//P
			{ "000000111", "1010101100110", },//Q
			{ "100000110", "1101010110010", },//R
			{ "001000110", "1011010110010", },//S
			{ "000010110", "1010110110010", },//T
			{ "110000001", "1100101010110", },//U
			{ "011000001", "1001101010110", },//V
			{ "111000000", "1100110101010", },//W
			{ "010010001", "1001011010110", },//X
			{ "110010000", "1100101101010", },//Y
			{ "011010000", "1001101101010", },//Z
			{ "010000101", "1001010110110", },//-
			{ "110000100", "1100101011010", },//.
			{ "011000100", "1001101011010", },//
			{ "010101000", "1001001001010", },//$
			{ "010100010", "1001001010010", },///
			{ "010001010", "1001010010010", },//+
			{ "000101010", "1010010010010", },//%
			{ "010010100", "1001011011010", },//*
		};
		#endregion

		#region private static readonly string[,] Ean13Codes
		private static readonly string[,] Ean13Codes = new string[,]
		{
			{"AAAAAA", "0001101", "0100111", "1110010", },//0
			{"AABABB", "0011001", "0110011", "1100110", },//1
			{"AABBAB", "0010011", "0011011", "1101100", },//2
			{"AABBBA", "0111101", "0100001", "1000010", },//3
			{"ABAABB", "0100011", "0011101", "1011100", },//4
			{"ABBAAB", "0110001", "0111001", "1001110", },//5
			{"ABBBAA", "0101111", "0000101", "1010000", },//6
			{"ABABAB", "0111011", "0010001", "1000100", },//7
			{"ABABBA", "0110111", "0001001", "1001000", },//8
			{"ABBABA", "0001011", "0010111", "1110100", },//9
			{"Type", "A", "B", "C"},//9
		};
		#endregion

		#region private static readonly string[,] Code128Codes
		private static readonly string[,] Code128Codes =
		{
			{ "11011001100", AsciiString.SP, null, },// "212222", },
			{ "11001101100", AsciiString.EXCLAMATION, null, },// "222122", },
			{ "11001100110", AsciiString.BACKSLASH, null, },// "222221", },
			{ "10010011000", AsciiString.SHARP, null, },// "121223", },
			{ "10010001100", AsciiString.DOLLAR, null, },// "121322", },
			{ "10001001100", AsciiString.PERCENT, null, },// "131222", },
			{ "10011001000", AsciiString.AMPERSAND, null, },// "122213", },
			{ "10011000100", AsciiString.APOSTROPHE, null, },// "122312", },
			{ "10001100100", AsciiString.LP, null, },// "132212", },
			{ "11001001000", AsciiString.RP, null, },// "221213", },
			{ "11001000100", AsciiString.ASTERISK, null, },// "221312", },
			{ "11000100100", AsciiString.PLUS, null, },// "231212", },
			{ "10110011100", AsciiString.COMMA, null, },// "112232", },
			{ "10011011100", AsciiString.MINUS, null, },// "122132", },
			{ "10011001110", AsciiString.PERIOD, null, },// "122231", },
			{ "10111001100", AsciiString.SLASH, null, },// "113222", },
			{ "10011101100", AsciiString.D0, null, },// "123122", },
			{ "10011100110", AsciiString.D1, null, },// "123221", },
			{ "11001110010", AsciiString.D2, null, },// "223211", },
			{ "11001011100", AsciiString.D3, null, },// "221132", },
			{ "11001001110", AsciiString.D4, null, },// "221231", },
			{ "11011100100", AsciiString.D5, null, },// "213212", },
			{ "11001110100", AsciiString.D6, null, },// "223112", },
			{ "11101101110", AsciiString.D7, null, },// "312131", },
			{ "11101001100", AsciiString.D8, null, },// "311222", },
			{ "11100101100", AsciiString.D9, null, },// "321122", },
			{ "11100100110", AsciiString.COLON, null, },// "321221", },
			{ "11101100100", AsciiString.SEMICOLON, null, },// "312212", },
			{ "11100110100", AsciiString.LT, null, },// "322112", },
			{ "11100110010", AsciiString.EQUAL, null, },// "322211", },
			{ "11011011000", AsciiString.GT, null, },// "212123", },
			{ "11011000110", AsciiString.QUESTION, null, },// "212321", },
			{ "11000110110", AsciiString.AT, null, },// "232121", },
			{ "10100011000", AsciiString.A, null, },// "111323", },
			{ "10001011000", AsciiString.B, null, },// "131123", },
			{ "10001000110", AsciiString.C, null, },// "131321", },
			{ "10110001000", AsciiString.D, null, },// "112313", },
			{ "10001101000", AsciiString.E, null, },// "132113", },
			{ "10001100010", AsciiString.F, null, },// "132311", },
			{ "11010001000", AsciiString.G, null, },// "211313", },
			{ "11000101000", AsciiString.H, null, },// "231113", },
			{ "11000100010", AsciiString.I, null, },// "231311", },
			{ "10110111000", AsciiString.J, null, },// "112133", },
			{ "10110001110", AsciiString.K, null, },// "112331", },
			{ "10001101110", AsciiString.L, null, },// "132131", },
			{ "10111011000", AsciiString.M, null, },// "113123", },
			{ "10111000110", AsciiString.N, null, },// "113321", },
			{ "10001110110", AsciiString.O, null, },// "133121", },
			{ "11101110110", AsciiString.P, null, },// "313121", },
			{ "11010001110", AsciiString.Q, null, },// "211331", },
			{ "11000101110", AsciiString.R, null, },// "231131", },
			{ "11011101000", AsciiString.S, null, },// "213113", },
			{ "11011100010", AsciiString.T, null, },// "213311", },
			{ "11011101110", AsciiString.U, null, },// "213131", },
			{ "11101011000", AsciiString.V, null, },// "311123", },
			{ "11101000110", AsciiString.W, null, },// "311321", },
			{ "11100010110", AsciiString.X, null, },// "331121", },
			{ "11101101000", AsciiString.Y, null, },// "312113", },
			{ "11101100010", AsciiString.Z, null, },// "312311", },
			{ "11100011010", AsciiString.LSB, null, },// "332111", },
			{ "11101111010", AsciiString.BACKSLASH, null, },// "314111", },
			{ "11001000010", AsciiString.RSB, null, },// "221411", },
			{ "11110001010", AsciiString.CIRCUMFLEX, null, },// "431111", },
			{ "10100110000", AsciiString.UNDERSCORE, null, },// "111224", },
			{ "10100001100", AsciiString.NUL, AsciiString.BACKTICK, },// "111422", },
			{ "10010110000", AsciiString.SOH, AsciiString.a, },// "121124", },
			{ "10010000110", AsciiString.STX, AsciiString.b, },// "121421", },
			{ "10000101100", AsciiString.ETX, AsciiString.c, },// "141122", },
			{ "10000100110", AsciiString.EOT, AsciiString.d, },// "141221", },
			{ "10110010000", AsciiString.ENQ, AsciiString.e, },// "112214", },
			{ "10110000100", AsciiString.ACK, AsciiString.f, },// "112412", },
			{ "10011010000", AsciiString.BEL, AsciiString.g, },// "122114", },
			{ "10011000010", AsciiString.BS, AsciiString.h, },// "122411", },
			{ "10000110100", AsciiString.HT, AsciiString.i, },// "142112", },
			{ "10000110010", AsciiString.LF, AsciiString.j, },// "142211", },
			{ "11000010010", AsciiString.VT, AsciiString.k, },// "241211", },
			{ "11001010000", AsciiString.FF, AsciiString.l, },// "221114", },
			{ "11110111010", AsciiString.CR, AsciiString.m, },// "413111", },
			{ "11000010100", AsciiString.SO, AsciiString.n, },// "241112", },
			{ "10001111010", AsciiString.SI, AsciiString.o, },// "134111", },
			{ "10100111100", AsciiString.DLE, AsciiString.p, },// "111242", },
			{ "10010111100", AsciiString.DC1, AsciiString.q, },// "121142", },
			{ "10010011110", AsciiString.DC2, AsciiString.r, },// "121241", },
			{ "10111100100", AsciiString.DC3, AsciiString.s, },// "114212", },
			{ "10011110100", AsciiString.DC4, AsciiString.t, },// "124112", },
			{ "10011110010", AsciiString.NAK, AsciiString.u, },// "124211", },
			{ "11110100100", AsciiString.SYN, AsciiString.v, },// "411212", },
			{ "11110010100", AsciiString.ETB, AsciiString.w, },// "421112", },
			{ "11110010010", AsciiString.CAN, AsciiString.x, },// "421211", },
			{ "11011011110", AsciiString.EM, AsciiString.y, },// "212141", },
			{ "11011110110", AsciiString.SUB, AsciiString.z, },// "214121", },
			{ "11110110110", AsciiString.ESC, AsciiString.LBB, },// "412121", },
			{ "10101111000", AsciiString.FS, AsciiString.VERTICAL, },// "111143", },
			{ "10100011110", AsciiString.GS, AsciiString.RBB, },// "111341", },
			{ "10001011110", AsciiString.RS, AsciiString.TILDE, },// "131141", },
			{ "10111101000", AsciiString.US, AsciiString.DEL, },// "114113", },
			{ "10111100010", "FNC3", "FNC3", },// "114311", },96
			{ "11110101000", "FNC2", "FNC2", },// "411113", },97
			{ "11110100010", "SHIFT", "SHIFT", },// "411311", },98
			{ "10111011110", "CODEC", "CODEC", },// "113141", },99
			{ "10111101110", "CODEB", "FNC4", },// "114131", },CODEB
			{ "11101011110", "FNC4", "CODEA", },// "311141", },CODEA
			{ "11110101110", "FNC1", "FNC1", },// "411131", },FNC1
			{ "11010000100", "StartA", "StartA", },// "211412", },103
			{ "11010010000", "StartB", "StartB", },// "211214", },
			{ "11010011100", "StartC", "StartC", },// "211232", },
			{ "1100011101011", null, null, },// "2331112", },
		};
		#endregion

		/// <summary>
		/// 编条码128
		/// </summary>
		/// <param name="code">条码内容</param>
		/// <returns>条码编码</returns>
		public static string EncodingCode128(string code)
		{
			const byte A = 103;

			if (string.IsNullOrEmpty(code))
				return code;

			var c = code[0];
			var t = string.Empty;
			var cl = code.Length;
			var ai = new byte[cl * 2 + 1];
			var ci = 0;
			var ct = A;//B
			if (cl == 1)
			{
				if (c >= AsciiChar.SP)//如果不是控制符，则为B
					ct = A + 1;//B
				else
					ct = A;//A
			}
			else if (c >= AsciiChar.D0 && c <= AsciiChar.D9)//如果是数字，判断第二个
			{
				c = code[1];
				if (c >= AsciiChar.D0 && c <= AsciiChar.D9)//第二个是数字则为C
					ct = A + 2;//C
				else if (c >= AsciiChar.SP)//如果不是控制符，则为B
					ct = A + 1;//B
				else//否则为A
					ct = A;//A
			}
			else//A | B
			{
				if (c >= AsciiChar.SP)//如果不是控制符，则为B
					ct = A + 1;//B
				else//否则为A
					ct = A;//A
			}
			ai[ci] = ct;
			for (var i = 0; i < cl; i++)
			{
				ci++;
				c = code[i];
				if (ct == A)//A
				{
					if (c >= AsciiChar.BACKTICK)
					{
						ct = A + 1;						//B
						ai[ci] = A - 3;
						t += Code128Codes[ai[ci], 0];
						i--;							//后退重来
						continue;
					}

					if (cl > i + 3 && c >= AsciiChar.D0 && c <= AsciiChar.D9 &&
						code[i + 3] >= AsciiChar.D0 && code[i + 3] <= AsciiChar.D9 &&
						code[i + 2] >= AsciiChar.D0 && code[i + 2] <= AsciiChar.D9 &&
						code[i + 1] >= AsciiChar.D0 && code[i + 1] <= AsciiChar.D9)
					{
						ct = A + 2;						//C
						ai[ci] = A - 4;
						t += Code128Codes[ai[ci], 0];
						i--;							//后退重来
						continue;
					}

					if (c >= AsciiChar.SP)
						ai[ci] = (byte)(c - AsciiChar.SP);
					else
						ai[ci] = (byte)(c + 64);
					t += Code128Codes[ai[ci], 0];
					continue;
				}

				if (ct == A + 1)//B
				{
					if (c < AsciiChar.SP)
					{
						ct = A;							//B
						ai[ci] = A - 2;
						t += Code128Codes[ai[ci], 0];
						i--;							//后退重来
						continue;
					}

					if (cl > i + 3 && c >= AsciiChar.D0 && c <= AsciiChar.D9 &&
						code[i + 3] >= AsciiChar.D0 && code[i + 3] <= AsciiChar.D9 &&
						code[i + 2] >= AsciiChar.D0 && code[i + 2] <= AsciiChar.D9 &&
						code[i + 1] >= AsciiChar.D0 && code[i + 1] <= AsciiChar.D9)
					{
						ct = A + 2;						//C
						ai[ci] = A - 4;
						t += Code128Codes[ai[ci], 0];
						i--;							//后退重来
						continue;
					}

					if (c >= AsciiChar.BACKTICK)
						ai[ci] = (byte)(c - AsciiChar.BACKTICK + 64);
					else
						ai[ci] = (byte)(c - AsciiChar.SP);
					t += Code128Codes[ai[ci], 0];
					continue;
				}

				if (i >= cl - 1)//最后一位了，无法使用C
				{
					if (c >= AsciiChar.SP)//如果不是控制符，则为B
					{
						ct = A + 1;//B
						ai[ci] = A - 3;
					}
					else
					{
						ct = A;//A
						ai[ci] = A - 2;
					}
					t += Code128Codes[ai[ci], 0];
					i--;//后退重来
					continue;
				}

				if (c < AsciiChar.D0 || c > AsciiChar.D9)//不是数字，无法使用C
				{
					if (c >= AsciiChar.SP)//如果不是控制符，则为B
					{
						ct = A + 1;//B
						ai[ci] = A - 3;
					}
					else
					{
						ct = A;//A
						ai[ci] = A - 2;
					}
					t += Code128Codes[ai[ci], 0];
					i--;//后退重来
					continue;
				}

				ai[ci] = (byte)((c - AsciiChar.D0) * 10);
				c = code[i + 1];									//取下一字符
				if (c < AsciiChar.D0 || c > AsciiChar.D9)		//不是数字，无法使用C
				{
					if (c >= AsciiChar.SP)//如果不是控制符，则为B
					{
						ct = A + 1;//B
						ai[ci] = A - 3;
					}
					else
					{
						ct = A;//A
						ai[ci] = A - 2;
					}
					t += Code128Codes[ai[ci], 0];
					i--;//后退重来
					continue;
				}

				ai[ci] = (byte)(ai[ci] + c - AsciiChar.D0);
				t += Code128Codes[ai[ci], 0];
				i++;
			}
			t = Code128Codes[ai[0], 0] + t + Code128Codes[GetCode128ISBN(ai), 0] + Code128Codes[Code128Codes.GetLength(0) - 1, 0];
			return t;
		}

		/// <summary>
		/// 编条码93
		/// </summary>
		/// <param name="code">条码内容</param>
		/// <returns>条码编码</returns>
		public static string EncodingCode93(string code)
		{
			if (string.IsNullOrEmpty(code))
				return code;

			var m = Code93Codes.Length - 2;
			var t = Code93Codes[m];
			var ls = new List<int>(20);
			code = code.ToUpper();
			for (var i = 0; i < code.Length; i++)
			{
				if (code[i] == '+')
					return null;

				m = Code93Chars.IndexOf(code[i]);
				if (m == -1)
					return null;

				t += Code93Codes[m];
				ls.Add(m);
			}
			m = 0;
			for (var i = ls.Count - 1; i >= 0; i--)
				m += (((ls.Count - 1 - i) % 20) + 1) * ls[i];
			m %= (Code93Codes.Length - 2);
			t += Code93Codes[m];
			ls.Add(m);
			m = 0;
			for (var i = ls.Count - 1; i >= 0; i--)
				m += (((ls.Count - 1 - i) % 15) + 1) * ls[i];
			m %= (Code93Codes.Length - 2);
			t += Code93Codes[m];
			ls.Add(m);
			t += Code93Codes[Code93Codes.Length - 1];
			ls.Clear();
			return t;
		}

		/// <summary>
		/// 编条码39
		/// </summary>
		/// <param name="code">条码内容</param>
		/// <returns>条码编码</returns>
		public static string EncodingCode39(string code)
		{
			const int I = 1;
			if (string.IsNullOrEmpty(code))
				return code;

			var t = Code39Codes[Code39Codes.GetLength(0) - 1, I]; //添加起始码“*”.
			var il = code.Length;
			code = code.ToUpper();
			for (var i = 0; i < il; i++)
			{
				if (Code39Chars.IndexOf(code[i]) == -1 || code[i] == '*')//非法字符校验
					return null;

				t = t + "0" + Code39Codes[Code39Chars.IndexOf(code[i]), I];//编码
			}
			t = t + "0" + Code39Codes[Code39Codes.GetLength(0) - 1, I];//添加结束码“*”
			return t;
		}

		/// <summary>
		/// 编条码13
		/// </summary>
		/// <param name="code">条码内容</param>
		/// <returns>条码编码</returns>
		public static string EncodingEan13(string code)
		{
			if (string.IsNullOrEmpty(code))
				return code;

			if (code.Length == 12)
				code = code + BarCode.GetEan13ISBN(code);
			if (code.Length != 13)
				throw new Exception("数字不是13位!");

			var v = "101";
			var t = Ean13Codes[code[0] - '0', 0].ToCharArray();
			for (var i = 1; i < 7; i++)
				v += Ean13Codes[code[i] - '0', t[i - 1] - 'A' + 1];
			v += "01010";
			for (var i = 7; i < 13; i++)
				v += Ean13Codes[code[i] - '0', 3];
			v += "101";
			return v;
		}

		/// <summary>
		/// 画条码128
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码内容</param>
		/// <param name="dest"></param>
		public static void DrawCode128(Graphics graphics, string code, Rectangle dest)
		{
			DrawCode128(graphics, code, dest.Width, dest.Height, dest.X, dest.Y);
		}
		/// <summary>
		/// 画条码128
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码内容</param>
		/// <param name="width">宽度，应为内容字符数加3，起始符与一位校验符</param>
		/// <param name="height">高度</param>
		/// <param name="x">水平位置</param>
		/// <param name="y">垂直位置</param>
		public static void DrawCode128(Graphics graphics, string code, int width, int height = 0, int x = 0, int y = 0)
		{
			if (string.IsNullOrEmpty(code))
				return;

			var t = BarCode.EncodingCode128(code);
			BarCode.DrawAny(graphics, t, code, width, height, x, y);
			return;
		}

		/// <summary>
		/// 画条码93
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码内容</param>
		/// <param name="dest"></param>
		public static void DrawCode93(Graphics graphics, string code, Rectangle dest)
		{
			DrawCode93(graphics, code, dest.Width, dest.Height, dest.X, dest.Y);
		}
		/// <summary>
		/// 画条码93
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码内容</param>
		/// <param name="width">宽度，应为内容字符数加4，起始符与两位校验符</param>
		/// <param name="height">高度</param>
		/// <param name="x">水平位置</param>
		/// <param name="y">垂直位置</param>
		public static void DrawCode93(Graphics graphics, string code, int width, int height = 0, int x = 0, int y = 0)
		{
			if (string.IsNullOrEmpty(code))
				return;

			var t = BarCode.EncodingCode93(code);
			BarCode.DrawAny(graphics, t, code, width, height, x, y);
			return;
		}

		/// <summary>
		/// 画条码39
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码内容</param>
		/// <param name="dest"></param>
		public static void DrawCode39(Graphics graphics, string code, Rectangle dest)
		{
			DrawCode39(graphics, code, dest.Width, dest.Height, dest.X, dest.Y);
		}
		/// <summary>
		/// 画条码39
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码内容</param>
		/// <param name="width">宽度，应为内容字符数加2</param>
		/// <param name="height">高度</param>
		/// <param name="x">水平位置</param>
		/// <param name="y">垂直位置</param>
		public static void DrawCode39(Graphics graphics, string code, int width, int height = 0, int x = 0, int y = 0)
		{
			if (string.IsNullOrEmpty(code))
				return;

			var t = BarCode.EncodingCode39(code);
			BarCode.DrawAny(graphics, t, code, width, height, x, y);
			return;
		}

		/// <summary>
		/// 画条码13
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码内容</param>
		/// <param name="dest"></param>
		public static void DrawEan13(Graphics graphics, string code, Rectangle dest)
		{
			DrawEan13(graphics, code, dest.Width, dest.Height, dest.X, dest.Y);
		}
		/// <summary>
		/// 画条码13
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码内容</param>
		/// <param name="width">宽度</param>
		/// <param name="height">高度</param>
		/// <param name="x">水平位置</param>
		/// <param name="y">垂直位置</param>
		public static void DrawEan13(Graphics graphics, string code, int width, int height = 0, int x = 0, int y = 0)
		{
			if (string.IsNullOrEmpty(code))
				return;

			var t = BarCode.EncodingEan13(code);
			if(string.IsNullOrEmpty(t))
				return;

			var l = t.Length;
			if (height < 16)
				height = width / 2;
			if (code.Length == 12)
				code += BarCode.GetEan13ISBN(code);
			var m = code.Length;
			var tw = width / m * 1F;
			var th = height / 4F;
			var f = tw > th ? th : tw;
			var ft = new Font(SystemFonts.CaptionFont.FontFamily, f, GraphicsUnit.Pixel);
			var ts = graphics.MeasureString(code, ft);
			tw = ts.Width / m;
			th = ts.Height / 2;
			m = (int)(tw * 2);
			if (width < 2 * l + m)
				width = 2 * l + m;
			m = (width - m) / l;
			using (var ms = new MemoryStream())
			{
				using (var bmp = new Bitmap(1, 1))
				{
					using (var gmf = Graphics.FromImage(bmp))
					{
						using (var mf = new Metafile(ms, gmf.GetHdc()))
						{
							using (var g = Graphics.FromImage(mf))
							{
								g.DrawString(code[0].ToString(), ft, Brushes.Black, x - tw / 4F, y + height - th);
								for (var i = 0; i < l; i++)
								{
									f = x + i * m + tw;// *1.5F;
									if (t[i] != '0')
									{
										if (i == 0 || i == 2 || i == 46 || i == 48 || i == 92 || i == 94)
											g.FillRectangle(Brushes.Black, f, y, m, height);
										else
											g.FillRectangle(Brushes.Black, f, y, m, height - th);
									}
									if (i > 49)
									{
										if ((i - 8) % 7 == 0 && i < 90)
											g.DrawString(code[(i - 8) / 7 + 1].ToString(), ft, Brushes.Black, f, y + height - th);
									}
									else// if (i <= 49)
									{
										if (i > 0 && (i - 3) % 8 == 0)
											g.DrawString(code[(i - 3) / 8 + 1].ToString(), ft, Brushes.Black, f - tw * 2 / (8 - (i - 3) / 8), y + height - th);//i * m + x + tw - i / 7.5F
									}
								}
								g.DrawString(">", ft, Brushes.Black, l * m + x + tw, y + height - th);
								g.Save();
								g.Dispose();
							}
							Emf.Draw(graphics, mf, x, y, width, height);
							mf.Dispose();
						}
						gmf.Dispose();
					}
					bmp.Dispose();
				}
				ms.Dispose();
			}
			graphics = null;
		}

		/// <summary>
		/// 画条码
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码编码</param>
		/// <param name="data">条码内容</param>
		/// <param name="dest"></param>
		public static void DrawAny(Graphics graphics, string code, string data, Rectangle dest)
		{
			DrawAny(graphics, code, data, dest.Width, dest.Height, dest.X, dest.Y);
		}
		/// <summary>
		/// 画条码
		/// </summary>
		/// <param name="graphics">GDI</param>
		/// <param name="code">条码编码</param>
		/// <param name="data">条码内容</param>
		/// <param name="width">宽度</param>
		/// <param name="height">高度</param>
		/// <param name="x">水平位置</param>
		/// <param name="y">垂直位置</param>
		public static void DrawAny(Graphics graphics, string code, string data, int width, int height = 0, int x = 0, int y = 0)
		{
			var tl = data.Length;
			if (data == null)
				data = string.Empty;
			if (height < 16)
				height = width / 2;
			var tw = width / tl * 1F;
			var th = height / 4F;
			var f = tw > th ? th : tw;
			var ft = new Font(SystemFonts.CaptionFont.FontFamily, f, GraphicsUnit.Pixel);
			var ts = graphics.MeasureString(data, ft);
			tw = ts.Width / tl;
			th = ts.Height / 2;
			var cl = code.Length;
			var cw = cl / tl;
			if (width < 2 * cl)
				width = 2 * cl;
			var m = width / cl;
			//x = x + (width - m * cl) / 2;
			using (var ms = new MemoryStream())
			{
				using (var bmp = new Bitmap(1, 1))
				{
					using (var gmf = Graphics.FromImage(bmp))
					{
						using (var mf = new Metafile(ms, gmf.GetHdc()))
						{
							using (var g = Graphics.FromImage(mf))
							{
								for (var i = 0; i < cl; i++)
								{
									f = i * m + x * 1F;
									if (code[i] != '0')
									{
										if (i <= 1 || i > cl - 4)
											g.FillRectangle(Brushes.Black, f, y, m, height);
										else
											g.FillRectangle(Brushes.Black, f, y, m, height - th);
									}
									//if (th > 0 && i % cw == 0 && i / cw < tl && data[i / cw] > AsciiChar.SP)
									//	g.DrawString(data[i / cw].ToString(), ft, Brushes.Black, f + tw * 1.5F, y + height - th);
								}
								f = cl * m / tl;
								for (var i = 0; i < tl; i++)
									g.DrawString(data[i].ToString(), ft, Brushes.Black, f * i + m + x, y + height - th);
								g.Save();
								g.Dispose();
							}
							Emf.Draw(graphics, mf, x, y, width, height);
							mf.Dispose();
						}
						gmf.Dispose();
					}
					bmp.Dispose();
				}
				ms.Dispose();
			}
			graphics = null;
		}

		private static byte GetCode128ISBN(byte[] indexs)
		{
			var i = indexs[0] * 1;
			for (var ii = indexs.Length - 1; ii > 0; ii--)
				i = i + indexs[ii] * ii % 103;
			return (byte)(i % 103);
		}

		/// <summary> 
		/// 获得条码的最后一位（验证位） 
		/// </summary> 
		/// <param name="code">条码</param> 
		/// <returns>条码校验码</returns> 
		public static char GetEan13ISBN(string code)
		{
			if (string.IsNullOrEmpty(code))
				return '\0';

			var v = 0;
			var x = 1;   //权值 
			var i = 0;
			foreach (var c in code)
			{
				if (c < '0' || c > '9')
					return '\0'; // 非数字

				v = v + (c - '0') * x;
				x = x == 1 ? 3 : 1;
				if (++i == 12)
					break;
			}
			if (i != 12)
				return '\0';

			x = '0' + 10 - v % 10;
			if (x > '9')
				return '0';

			return (char)x;
		}

		/*
		var filePath = @”D:\face.emf”;
		var bmp = new Bitmap(220, 220);
		var gs = Graphics.FromImage(bmp);
		var mf = new Metafile(filePath, gs.GetHdc());
		var g = Graphics.FromImage(mf);
		g.FillEllipse(Brushes.Gray, 0, 0, 100, 100);
		g.DrawEllipse(Pens.Black, 0, 0, 100, 100);
		g.DrawArc(new Pen(Color.Red, 10), 20, 20, 60, 60, 30, 120);
		g.Save();//只可这里保存才是EMF格式，对象mf或gs保存都只能是PNG格式。
		g.Dispose();
		mf.Dispose();
		*/
	}
}
